import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Random;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSplitPane;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class TestRunner{

	JFrame frame;
	private JProgressBar progressBar;
	private IconResizer resizer = new IconResizer(null);
	private static Test test;//change structure
	private static int probindex;
	private static int sessindex;
	private TokenBoard board;
	private Timer datacollector = new Timer();
	public ArrayList<Double> sampleresponse = new ArrayList<Double>();
	public ArrayList<Double> answerresponse = new ArrayList<Double>();
	public ArrayList<Boolean> answers = new ArrayList<Boolean>();
	public boolean mouseSampleListenerActive = true;
	public boolean mouseComparisonListenerActive = true;
	int comparisondelay = 0;
	int answerdelay = 0;
	String subjectName;
	CSVWriter datarecorder;
	DateFormat dateFormat;
	Date date;
	Random randGen;
	double delaysample;
	
	
	/**
	 * Create the application.
	 * @throws IOException 
	 * @throws InterruptedException 
	 */
	
	public TestRunner(Test t, String subName) throws IOException{
		test = t;
		subjectName = subName;
		datarecorder = new CSVWriter("subjects/"+subName+"/data.csv");
		initialize();
		this.frame.setVisible(true);
	}
	
	/**
	 * Initialize the contents of the frame.
	 * @throws IOException 
	 */
	private void initialize() throws IOException {
		probindex = 0;
		sessindex = 0;
		frame = new JFrame();
		frame.setBounds(100, 100, 758, 498);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(null);
		comparisondelay = test.getComparisonDelay()*1000;
		answerdelay = test.getAnswerDelay()*1000;
		board = test.getTokenBoard();
		dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		date = new Date();
		randGen = new Random();
		problemLoader(test.getSession(0));
	}
	
	public void problemLoader(final Session session) throws IOException{
		if (session.isRewardedPhase()){
			datarecorder.append(subjectName+","+//name
								dateFormat.format(date)+","+//date
								session.getName()+","+//session name
								session.getSessionType()+","+//session type
								session.getProblem(probindex).MTS+","+//MTS activated, true false
								test.getAnswerDelay()+","+//Delay set
								session.getProgressBar()+","+//Progress bar activated, true false
								session.getProblem(probindex).comparisonCounter+","+//comparisons
								test.getTokenBoard().getTokens()+","+//tokens available
								test.getTokenBoard().getTokenName(session.getProblem(probindex).getReinforcer())+","+//token rewarded
								probindex);
		}
		else {
			datarecorder.append(subjectName+","+//name
								dateFormat.format(date)+","+
								session.getName()+","+
								session.getSessionType()+","+
								session.getProblem(probindex).MTS+","+
								test.getAnswerDelay()+","+
								session.getProgressBar()+","+
								session.getProblem(probindex).comparisonCounter+","+
								" "+","+" "+","+
								probindex);
				
		}
		frame.getContentPane().removeAll();
		final JLabel sample = new JLabel("");
		mouseSampleListenerActive = true;
		sample.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
					if (mouseSampleListenerActive){
					mouseSampleListenerActive = false;
					datacollector.stopTimer();//Stop timer when subject clicks on sample.
					try {
						Thread.sleep(comparisondelay);
						//problemUnloader(session);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					double temp = datacollector.getResult();
					sampleresponse.add(temp);
					delaysample = temp;
					System.out.println(sampleresponse.get(probindex) + " added");
					datacollector.startTimer();
					if (!(session.getProblem(probindex).isMTS())){
						sample.setVisible(false);
						sample.updateUI();
					}
				 	int division = frame.getWidth() / session.getProblem(probindex).getNoOfComparisons();
				 	int comparisons = session.getProblem(probindex).getNoOfComparisons();
				 	ArrayList<Integer> total = new ArrayList<Integer>();
				 	for (int i = 0; i < comparisons; i++){
				 		total.add(i);
				 	}
					for (int i = 0; i < comparisons; i++){ //draw comparisons.
						int temp1 = randGen.nextInt(total.size());
						int position = total.remove(temp1);
						int x = (division * position) + (division / 10);
						int width = ((division / 100) * 80);
						final JButton btnNewButton = new JButton("");
						mouseComparisonListenerActive = true;	
						if (session.getProblem(probindex).getComparison(i).getAnswer()){
						   btnNewButton.addMouseListener(new MouseAdapter() {
							   @Override
							   public void mouseClicked(MouseEvent arg0){
								   if (mouseComparisonListenerActive){
									   answers.add(true);
									   System.out.println(answers.get(probindex) + " answer!"); 
									   mouseComparisonListenerActive = false;
									   datacollector.stopTimer();
									   double temp = datacollector.getResult();
										try {
											datarecorder.append(","+test.getComparisonDelay()+","+//comparison delay
													"1"+","+
													temp+","+delaysample+"\n");//Start latency
										} catch (IOException e1) {
											// TODO Auto-generated catch block
											e1.printStackTrace();
										}
									   try {
											Thread.sleep(answerdelay);
										} catch (InterruptedException e) {
											// TODO Auto-generated catch block
											e.printStackTrace();
										}
									   answerresponse.add(temp);
									   System.out.println(answerresponse.get(probindex) + " added");
									   if (session.isRewardedPhase()){
										   //get problem reward type, a or b.
										   int reward = session.getProblem(probindex).getReinforcer();
										   board.giveReward(reward);
										   //show token bar since this is a rewarded phase.
										   //board.showBoard();
										   try {
											showboard(session);
										} catch (IOException e) {
											// TODO Auto-generated catch block
											e.printStackTrace();
										}
									   }
									   else waitscreen(session);
								   }
							   }
						   });
						} else {
							btnNewButton.addMouseListener(new MouseAdapter() {
								@Override
								public void mouseClicked(MouseEvent arg0){
									if (mouseComparisonListenerActive){
										mouseComparisonListenerActive = false;
										datacollector.stopTimer();
										try {
											Thread.sleep(answerdelay);
											waitscreen(session);
											//problemUnloader(session);
										} catch (InterruptedException e) {
											// TODO Auto-generated catch block
											e.printStackTrace();
										}
										double temp = datacollector.getResult();
										answerresponse.add(temp);
										System.out.println(answerresponse.get(probindex) + " added"); 
										answers.add(false);
										System.out.println(answers.get(probindex) + " answer!"); 
										try {
											datarecorder.append(","+test.getComparisonDelay()+","+//comparison delay
													"0"+","+
													temp+","+delaysample+"\n");
										} catch (IOException e1) {
											// TODO Auto-generated catch block
											e1.printStackTrace();
										}//Start latency
										try {
											Thread.sleep(answerdelay);
											waitscreen(session);
											//problemUnloader(session);
										} catch (InterruptedException e) {
											// TODO Auto-generated catch block
											e.printStackTrace();
										}
									}
								}	
							});
						}
						ImageIcon image = new ImageIcon(session.getProblem(probindex).getComparison(i).getImage());
						resizer.setImage(image);//call the resizer to fit image to button.
						resizer.resize(162, width);
						btnNewButton.setIcon(resizer.getImage());
						btnNewButton.setBounds(x, 239, width, 162);//height of the pictures is constant.
						frame.getContentPane().add(btnNewButton);
						btnNewButton.updateUI();
					}
				}
			}
		});
		ImageIcon image = new ImageIcon(session.getProblem(probindex).getSample());
		resizer.setImage(image);
		resizer.resize(162, 237);
		sample.setIcon(resizer.getImage());
		sample.setBounds(258, 21, 237, 162);
		frame.getContentPane().add(sample);
		datacollector.startTimer();//Start timer after sample as been drawn.
		intializeInfo(session);
	}
	
	//Draw progress bar if needed.
	private void intializeInfo(Session session){
		if (session.getProgressBar()){ //Get option if bar wants to be displayed or not.
			progressBar = new JProgressBar(0, session.getNoOfProblems());
			progressBar.setValue(probindex);
			progressBar.setBounds(69, 427, 600, 20);
			progressBar.setStringPainted(true);
			frame.getContentPane().add(progressBar);
		}
	}
	
	//Unload a problem
	private void problemUnloader(Session session) throws IOException{
		frame.getContentPane().removeAll();
		probindex++;
		if (probindex <= session.getNoOfProblems()){
			if (probindex < session.getNoOfProblems()){
				problemLoader(session);
			}
			else if (probindex == session.getNoOfProblems()){
				//Write arraylist content to file.
				//Draw 2 buttons, continue, leave.
				contScreen(session);
			}
			frame.repaint();
		}
	}
	
	private void sessionUnloader() throws IOException{
		writeToFile();
		frame.getContentPane().removeAll();
		if (sessindex < test.getNoOfSessions()){
			probindex = 0;
			Session nextsession = test.getSession(sessindex);
			problemLoader(nextsession);
			frame.repaint();
		}
	}
	
	private void writeToFile() {
		System.out.println("Phase "+ sessindex);
		for (double d : sampleresponse){
			System.out.print(d+",");
		}
		for (double d : answerresponse){
			System.out.print(d+",");
		}
		for (boolean b : answers){
			if (b) System.out.print("Correct,");
			else System.out.print("Wrong,");
		}
	}

	private void waitscreen(final Session session) {
		frame.getContentPane().removeAll();
		JButton btnNewButton_1 = new JButton("Continue");
		btnNewButton_1.setBounds(508, 437, 244, 33);
		btnNewButton_1.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				try {
					problemUnloader(session);
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});
		frame.add(btnNewButton_1);
		frame.repaint();
	}
	
	//Draw Token board
	private void showboard(final Session session) throws IOException {
		frame.dispose();
		final JFrame frame = new JFrame();
		frame.setBounds(100, 100, 758, 498);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JPanel contentPane = new JPanel();
		
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(new BorderLayout(0, 0));
		
		frame.setContentPane(contentPane);
		
		JPanel panel = new JPanel();
		contentPane.add(panel, BorderLayout.CENTER);
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		
		JPanel panel_1 = new TokenBoardPopup(board);
		panel.add(panel_1);
		panel_1.setAlignmentX(Component.RIGHT_ALIGNMENT);
		
		panel.add(Box.createHorizontalGlue());

		JButton btnNewButton = new JButton("Continue");
		btnNewButton.setAlignmentX(Component.RIGHT_ALIGNMENT);
		panel.add(btnNewButton);
		
		btnNewButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				System.out.println("CLICKED!");
				frame.dispose();
				try {
					resetframe(session);
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});

		//test.add(board);
		frame.repaint();
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
	}
	
	//reset frame to the Test Runner.
	private void resetframe(Session session) throws IOException{
		frame = new JFrame();
		frame.setBounds(100, 100, 758, 498);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(null);
		frame.setVisible(true);
		problemUnloader(session);
	}

	private void contScreen(final Session session){	
		final JSplitPane splitPane = new JSplitPane();
		splitPane.setBounds(508, 437, 244, 33);
		frame.getContentPane().add(splitPane);
		
		JButton btnNewButton_1 = new JButton("Next Phase");
		btnNewButton_1.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				sessindex++;
				try {
					sessionUnloader();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});
		
		splitPane.setLeftComponent(btnNewButton_1);
		
		JButton btnNewButton_2 = new JButton("Replay Phase");
		btnNewButton_2.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				try {
					sessionUnloader();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});
		splitPane.setRightComponent(btnNewButton_2);
	}
}

